#ifndef RAYCASTER_H
#define RAYCASTER_H


#define XMAX 258
#define YMAX 258
#define ZMAX 258

#define MAXVOLUMETEXTURE 3

#include <GL/glew.h>
#include  "..\..\RenderingEngine\engineCore\OpenGLVolumeRenderer\Utility\GLSLProgram.h"
#include "..\..\RenderingEngine\engineCore\OpenGLVolumeRenderer\Utility\GLframebufferObject.h"
#include "..\..\RenderingEngine\engineCore\OpenGLVolumeRenderer\Utility\GLTexture.h"
#include "..\..\RenderingEngine\engineCore\OpenGLVolumeRenderer\Utility\GL.h"


#include <math.h>
#include <iostream>

// raycasting status
typedef struct
{
	bool phongshading;
	float isovalue;
	float stepsize;

}raycasterstatus;


class RayCaster
{
public:
	RayCaster();
	~RayCaster();
//new function///////////////////////////////////////////////////////
	bool loadNodePool3D(const char* filename, int sizeZ, int sizeY, int sizeX);//!!!note ZYX
	bool loadBlockPool(const char* filename, int sizeZ, int sizeY, int sizeX, int blockSize = 33);
	bool loadBlockPool(void* buffer, int sizeZ, int sizeY, int sizeX, int blockSize = 33);

///////////////////////////////////////////////////////////////////////////
	void InitializeRayCaster(); // create buffer, create program for raycasting

	void Render();
	void RenderMultiResOctree();
	void RenderScreenAlign();

	void setRotationMatrix(float[]);
	void setTranslation(float[]);
	void setTransferFunctionTexture(GLuint tex);

	//set raycasting status
	void setStepSize(float steps){stepsize = steps;}
	void setIsoValue(float isovalue){iso_value = isovalue;}
	void setVar(float var);
	//TODO
	void setRaycasterStatus( raycasterstatus status);

	double* getHistogram(){return histogram;}

	void saveCoreStatus(char* filename); //TF, view matrix

	//test
	void resize(int width, int height);
	int m_Width,m_Height;
	void _createProgram();

private:
	void _drawRenderTarget(int o_x, int o_y, GLuint tex);
	//program
	GLSLProgram vertexonlyprog, pass2prog, raycastprog2;
	//textures
	GLuint m_volumeTexture[MAXVOLUMETEXTURE];

	GLuint m_backface, m_raycast, framebuffer;

	//fbo
	FramebufferObject *fbo1, *fbo2, *fbo3D;

	//histogram
	double histogram[256];
	GLuint Lut;

	//state variables
	float m_x, m_y, m_z;
	float m_aspectRatio;
	float stepsize;
	float iso_value;
	float _var;

    float m_rotationY;
	float m_rotationX;
	float m_rotationMatrix[16];
	float m_pos[3];

	//temp
	unsigned char* _hiresVol,* _lowresVol;
public:
	///////////////////////TEST////////////////////
	GLSLProgram octreeRaycastprog, raycastprog;
	//GLuint tex_NodePool, tex_NodePool3D;
	//GLuint tex_BlockPool;
	////////////////////New non-bounding box version//////////////
	GLSLProgram screenRaycastprog;
	GLTexture *texNodePool3D;
	GLTexture *texBlockPool;
	float textureFilterOrder;
	float light_rotate[16];

private:
	//GLXX testing
	//GLTexture *texFront, *texBack;

	//
	unsigned int _blockPoolDim;
	unsigned int _nodePoolDim;
	unsigned int _blockSize;
	
	//volume size
	int _sizeX;
	int _sizeY;
	int _sizeZ;
};



#endif